home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
glass
/
glass.lha
/
GLASS
/
libcvr
/
symbol.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-11-09
|
4KB
|
174 lines
/* File: symbol.c
Symbol table manager.
*/
#include "all.h"
#include "cvr.h"
static int gensymworking;
static long int gensymnum;
/* This is the table of symbol strings. Each used symbol string should
occur here exactly once, so that a compare on equal names is
simplified to comparing the pointers to the strings. This must be
ensured by the routines 'addsymbol()' and 'gensymbol()'.
*/
static symbol symtab[HASHWIDTH];
/* The hashing function:
Return a value in the range 0..HASHWIDTH-1.
Current hashing function:
Add all characters in the given string and shift one position
after each addition.
*/
static unsigned int hash( s )
register char *s;
{
register unsigned int sum = 0;
while( *s != '\0' ){
sum += *s++;
sum <<= 1;
}
return( sum % HASHWIDTH );
}
/* make a new storage space for a symbol */
static symbol newsymbol( l, s )
symbol l;
char *s;
{
register symbol new;
new = (symbol) ckmalloc( (unsigned int) sizeof(*new) );
new->next = l;
new->symstr = s;
new->priority = 2;
return( new );
}
/* Try to locate string 'name' in the given list 'list'.
If the name occurs in the list, a pointer to the entry is returned,
else symbolNIL is returned.
*/
static symbol dofindsymbol( name, list )
register char *name;
register symbol list;
{
while( list != symbolNIL ){
if( strcmp( list->symstr, name ) == 0 ) return( list );
list = list->next;
}
return( symbolNIL );
}
/* Search the symbol table for the given symbol.
If the name occurs in the table, a pointer to the entry is returned,
else symbolNIL is returned.
*/
symbol findsymbol( name )
register char *name;
{
register symbol entry;
unsigned int hashval;
hashval = hash( name );
entry = dofindsymbol( name, symtab[hashval] );
return( entry );
}
/* Add string 'name' to the symbol table.
If the name already occurs in the table, a pointer to the old
entry is returned, else a new entry is added, and a pointer to this
new entry is returned.
This routine must ensure that for all symbols with the same name,
the same pointer is returned.
*/
symbol addsymbol( name )
register char *name;
{
register symbol entry;
unsigned int hashval;
if( gensymworking ){
fprintf(
stderr,
"You can't add symbols after using gensymbol() (name = '%s')\n",
name
);
exit( 1 );
}
hashval = hash( name );
entry = dofindsymbol( name, symtab[hashval] );
if( entry != symbolNIL ) return( entry );
entry = newsymbol( symtab[hashval], new_string( name ) );
symtab[hashval] = entry;
return( entry );
}
/* given a prefix 'pre', generate a new symbol with an unique name.
This is done by systematically generating names of the form
<pre><number> until a name is found that doesn't occur in the
list.
To ensure that the symbol remains unique, the flag 'gensymworking'
is set after the first symbol has been generated. After that it is
an error to add new symbols to the table using 'addsymbol()'.
*/
symbol gensymbol( pre )
char *pre;
{
unsigned int hashval;
register char *name;
register symbol entry;
name = new_string( pre );
name = ckrealloc( name, (unsigned int) strlen( pre ) + 30 );
for(;;){
(void) sprintf( name, "%s%ld", pre, gensymnum++ );
hashval = hash( name );
if( dofindsymbol( name, symtab[hashval] ) == symbolNIL ) break;
}
entry = newsymbol( symtab[hashval], name );
entry->priority = 0;
symtab[hashval] = entry;
return( entry );
}
/* initalize symbol routines */
void initsymbol(){
register int i;
for( i=0; i<HASHWIDTH; i++ ){
symtab[i] = symbolNIL;
}
gensymworking = FALSE;
gensymnum = 0;
}
/* flush symbol routines */
void flushsymbol(){
symbol s;
symbol n;
register int i;
for( i=0; i<HASHWIDTH; i++ ){
s = symtab[i];
while( s != symbolNIL ){
n = s->next;
free( s->symstr );
free( (char *) s );
s = n;
}
symtab[i] = symbolNIL;
}
gensymworking = FALSE;
gensymnum = 0;
}